﻿using System;
using System.IO;
using System.IO.Compression;
using System.Text;
using NUnit.Framework;
using Shinkansen.Core;
using Shinkansen.Extensions;
using Shinkansen.Support;

namespace Shinkansen.Test
{
    [TestFixture]
    public class HttpDecompressionTest
    {
        [Test]
        public void Decompressed_gzip_content_matches_orginal ()
        {
            HttpCompressor          compressor = new HttpCompressor (HttpCompressionMode.GZip);
            Func<Stream, Stream>    streamCreator = s => new GZipStream (s, CompressionMode.Decompress);
            Func<byte[], byte[]>    compressActor = content => DecompressTestContent (content, streamCreator);

            Test_validity_of_decompressed_content (compressActor, compressor);
        }

        [Test]
        public void Decompressed_deflate_content_matches_orginal ()
        {
            HttpCompressor          compressor = new HttpCompressor (HttpCompressionMode.Deflate);
            Func<Stream, Stream>    streamCreator = s => new DeflateStream (s, CompressionMode.Decompress);
            Func<byte[], byte[]>    compressActor = content => DecompressTestContent (content, streamCreator);

            Test_validity_of_decompressed_content (compressActor, compressor);
        }

        /// <summary>
        /// Decompress_contents the specified compress actor.
        /// </summary>
        /// <param name="compressActor">The compress actor.</param>
        /// <param name="compressor">The compressor.</param>
        private void Test_validity_of_decompressed_content (Func<byte[], byte[]> compressActor, HttpCompressor compressor)
        {
            string          text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit";
            byte[]          encoded = Encoding.UTF8.GetBytes (text);

            byte[] compressedResult = compressor.Compress (encoded);
            byte[] decompressedResult = compressActor (compressedResult);

            Assert.IsNotEmpty (decompressedResult);
            Assert.AreNotSame (compressedResult, decompressedResult);
            Assert.AreEqual (encoded, decompressedResult);
        }

        /// <summary>
        /// Decompresses the content of the test.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="streamCreator">The stream creator.</param>
        /// <returns></returns>
        private byte[] DecompressTestContent (byte[] content, Func<Stream, Stream> streamCreator)
        {
            using (MemoryStream contentStream = new MemoryStream (content))
            using (Stream stream = streamCreator (contentStream))
            using (MemoryStream outputStream = new MemoryStream ())
            {
                stream.CopyTo (outputStream);
                return outputStream.ToArray ();
            }
        }
    }
}
